#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>

#include "include/hid.h"
#include "include/chrsys.h"
#include "include/trajectory.h"

void initCaml() {
	char *arg[2];
	arg[0] = "--";
	arg[1] = 0;
	caml_startup(arg);
}

void chrSys_function(char *name) {
	value p = Val_int(0);
	value chrSys;
	
	chrSys = caml_callback(*caml_named_value("get_chrSys"), p);
	caml_callback(caml_get_public_method(chrSys, hash_variant(name)), chrSys);
}

int end_acquire() {
	value new_dir = Val_int(0);
	value result;
	result = caml_callback(*caml_named_value("end_acquire"), new_dir);
 	return (Int_val(result));
}

int update_chrsys(int dir, t_data data) {
	value new_dir = Val_int(dir);
	int result;
	char *name = NULL;
	result = Int_val(caml_callback(*caml_named_value("update"), new_dir));
	if (result != -1) {
		name = search_gesture(result, data->gestures);
		if (data->key_mode)
	      simulate_kbd(name);
	}
	if (name != NULL) {
		printf("Gesture recognized: %s %i\n", name, result);
		if (strcmp(name, "firefox") == 0)
			program("firefox");
		if (strcmp(name, "gedit") == 0)
			program("gedit");
		if (strcmp(name, "idev") == 0)
			program("idev");
	}
 	return (result);
}

void build_chrsys(int dir) {
	value new_dir = Val_int(dir);
	caml_callback(*caml_named_value("build"), new_dir);
}

void change_mode(int mode) {
	value p = Val_int(mode);
	caml_callback(*caml_named_value("ch_mode"), p);
}

char *to_string() {
	value p = Val_int(0);
	value result;
	result = caml_callback(*caml_named_value("to_string"), p);
	printf("%s\n", Bp_val(result));
 	return (Bp_val(result));
}

char *get_string(int id) {
	value p = Val_int(id);
	value result;
	result = caml_callback(*caml_named_value("get_string"), p);
 	return (Bp_val(result));
}

void save_chrSys(t_data data) {
	t_gesture gesture = data->gestures;
	FILE *f;
	char *buffer;

	f = fopen("gestures.emc", "w");
	while (gesture != NULL) {
		buffer = get_string(gesture->id);
		fwrite("name= ", sizeof(char), strlen("name= "), f);
		fwrite(gesture->name, sizeof(char), strlen(gesture->name), f);
		fwrite("\n", sizeof(char), strlen("\n"), f);
		fwrite(buffer, sizeof(char), strlen(buffer), f);
		fwrite("\n", sizeof(char), strlen("\n"), f);
		gesture = gesture->next;
	}
	fclose(f);
}

void load_chrSys(t_data data) {
	FILE *f = NULL;
	char buffer[255];
	char *tmp, *name;
	int id = -1;
	
	f = fopen("gestures.emc", "r");
	if (f) {
		while (fgets(buffer, 256, f)) {
			if (strncmp(buffer, "name= ", strlen("name= ")) == 0) {
				name = malloc(50 * sizeof(char));
				sscanf(buffer, "name= %s\n", name);
				continue;
			}	
			if (buffer[0] == '<') {
				chrSys_function("begin_acquire");
				tmp = buffer;
				tmp++;
				while(tmp[0] != '>') {
					build_chrsys((int)(tmp[0] - '0'));
					tmp++;
				}
				id = end_acquire();
				data->gestures = add_gesture(id, name, data->gestures);
			}
		}
		fclose(f);	
	}
}

char *search_gesture(int id, t_gesture gesture) {
	if (gesture == NULL)
		return(NULL);
	else {
		if (gesture->id == id) {
	      return(gesture->name);
		}
		else
			return(search_gesture(id, gesture->next));
	}
}

t_gesture add_gesture(int id, char *name, t_gesture gesture) {
	t_gesture new = malloc(sizeof(struct s_gesture));
	char *new_name = malloc(strlen(name) * sizeof(char));
	
	strcpy(new_name, name); 
	new->id = id;
	new->name = new_name;
	new->next = gesture;
	return(new);
}

void program(char *name) {
	char *argv[2];
	
	argv[0] = name;
	argv[1] = NULL;
	printf("Lancement de %s\n", name);
	if (!fork()) {
		execvp(name, argv);
		exit(0);
	}
}


